package com.neo.tiny.token.context;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

/**
 * @Description: 自定义AbstractAuthenticationToken
 * 参考{@link org.springframework.security.authentication.AbstractAuthenticationToken}
 * @Author: yqz
 * @CreateDate: 2022/11/13 17:19
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TokenAuthentication implements Authentication, CredentialsContainer {


    private Collection<? extends GrantedAuthority>  authorities;


    private UserDetails details;

    /**
     * 用户
     */
    protected Object principal;

    /**
     * 密码
     */
    protected Object credentials;

    /**
     * {@link com.neo.tiny.common.enums.UserTypeEnum}
     */
    private Integer userType;

    /**
     * 客户端id
     */
    private String clientId;

    private List<String> scopes;

    private boolean authenticated = false;

    public TokenAuthentication(Object principal, UserDetails details, Integer userType, String clientId) {
        this.principal = principal;
        this.details = details;
        this.userType = userType;
        this.clientId = clientId;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return details.getAuthorities();
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    @Override
    public Object getDetails() {
        return this.details;
    }


    @Override
    public boolean isAuthenticated() {
        return authenticated;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        this.authenticated = isAuthenticated;
    }

    @Override
    public String getName() {
        return details.getUsername();
    }

    @Override
    public void eraseCredentials() {
        eraseSecret(getCredentials());
        eraseSecret(getPrincipal());
        eraseSecret(details);
    }

    private void eraseSecret(Object secret) {
        if (secret instanceof CredentialsContainer) {
            ((CredentialsContainer) secret).eraseCredentials();
        }
    }
}
